#include "SceneNode.h"


SceneNode::SceneNode(void)
	:m_strSceneNodeName("NoDefine")
	,m_iNumChildren(0)
	,m_iNumMeshs(0)
	,m_pParent(NULL)
{
	D3DXMatrixIdentity(&m_matTransFromParent);
	D3DXMatrixIdentity(&m_matWorldTransform);
}


SceneNode::~SceneNode(void)
{
}

std::string SceneNode::GetNodeName()
{
	return m_strSceneNodeName;
}

void SceneNode::SetNodeName( const std::string& name )
{
	m_strSceneNodeName = name;
}

bool SceneNode::HasChildren()
{
	return m_iNumChildren>0;
}

int SceneNode::GetNumChildren()
{
	return m_iNumChildren;
}

bool SceneNode::HasMesh()
{
	return m_iNumMeshs>0;
}

void SceneNode::SetParentSceneNode( SceneNode* parent )
{
	m_pParent = parent;
}

void SceneNode::AddChildren( SceneNode* node )
{
	m_lstChildren.push_back(node);
}

D3DXMATRIX SceneNode::GetWorldMatrix()
{
	return m_matWorldTransform;
}

SceneNode* SceneNode::FindNodeByName( const std::string& name )
{
	if(this->m_strSceneNodeName == name)
		return this;

	SceneNode* pNode;
	std::list<SceneNode*>::const_iterator iter;
	for (iter=this->m_lstChildren.begin() ;iter!=this->m_lstChildren.end() ;++iter)
	{
		pNode = (*iter)->FindNodeByName(name);
		if( pNode != NULL )
			return pNode;
	}
	return NULL;
}

SceneNode* SceneNode::FindNodeBySubName( const std::string& name )
{
	std::string::size_type findPos;
	findPos = m_strSceneNodeName.find(name);
	if(findPos != std::string::npos)
		return this;

	SceneNode* pNode;
	std::list<SceneNode*>::const_iterator iter;
	for (iter=this->m_lstChildren.begin() ;iter!=this->m_lstChildren.end() ;++iter)
	{
		pNode = (*iter)->FindNodeBySubName(name);
		if( pNode != NULL )
			return pNode;
	}
	return NULL;
}

SceneNode* SceneNode::DeleteChildByName( const std::string& name )
{
	std::list<SceneNode*>::iterator iterChilde;
	SceneNode* pNode;
	for(iterChilde=m_lstChildren.begin() ;iterChilde!=m_lstChildren.end() ;++iterChilde)
	{
		if( (*iterChilde)->m_strSceneNodeName == name )
		{
			pNode = *iterChilde;
			//when delete the element from the list,it will return
			//so it has no iterator invalid problem
			m_lstChildren.erase(iterChilde);
			return pNode;
		}

		//find the node needed delete in it's child's children
		pNode = (*iterChilde)->DeleteChildByName(name);
		if(pNode)
			return pNode;
	}

	return NULL;
}

SceneNode* SceneNode::DeleteChildBySubName( const std::string& name )
{
	std::list<SceneNode*>::iterator iterChilde;
	SceneNode* pNode;
	for(iterChilde=m_lstChildren.begin() ;iterChilde!=m_lstChildren.end() ;++iterChilde)
	{
		if( (*iterChilde)->m_strSceneNodeName.find(name) != std::string::npos )
		{
			pNode = *iterChilde;
			//when delete the element from the list,it will return
			//so it has no iterator invalid problem
			m_lstChildren.erase(iterChilde);
			return pNode;
		}

		//find the node needed delete in it's child's children
		pNode = (*iterChilde)->DeleteChildByName(name);
		if(pNode)
			return pNode;
	}

	return NULL;
}

void SceneNode::MatrixFromParentIdentity()
{
	D3DXMatrixIdentity(&m_matTransFromParent);
}

void SceneNode::TranslationFromParent( const D3DXVECTOR3& translateVec )
{
	D3DXMATRIX T;
	D3DXMatrixTranslation(&T,translateVec.x,translateVec.y,translateVec.z);
	m_matTransFromParent = m_matTransFromParent * T;
}

SceneNode* SceneNode::Clone()
{
	SceneNode* pNode = new SceneNode();
	pNode->m_strSceneNodeName = m_strSceneNodeName+"Clone";
	pNode->m_iNumChildren = m_iNumChildren;
	pNode->m_iNumMeshs = m_iNumMeshs;
	pNode->m_pParent = NULL;
	pNode->m_matTransFromParent = m_matTransFromParent;
	pNode->m_matWorldTransform = m_matWorldTransform;

	std::list<int>::const_iterator iterMeshs;
	for(iterMeshs=m_lstMeshs.begin(); iterMeshs!=m_lstMeshs.end(); ++iterMeshs)
		pNode->m_lstMeshs.push_back(*iterMeshs);

	std::list<SceneNode*>::const_iterator iterChild;
	for(iterChild=m_lstChildren.begin(); iterChild!=m_lstChildren.end(); ++iterChild)
		pNode->AddChildren( (*iterChild)->Clone() );

	return pNode;
}
